package com.fulihui.wgj.service.template;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSONObject;
import com.fulihui.common.builder.rpc.RpcResultBuilder;
import com.fulihui.common.conv.BeanConv;
import com.fulihui.common.enums.SendLogStatusEnum;
import com.fulihui.common.error.Errors;
import com.fulihui.common.error.InvokeServiceException;
import com.fulihui.common.result.rpc.BaseResult;
import com.fulihui.common.result.rpc.SimpleResult;
import com.fulihui.common.util.ConditionValidator;
import com.fulihui.common.util.TemplateMsgCancelUtil;
import com.fulihui.wgj.config.properties.CommonProps;
import com.fulihui.wgj.dal.mybatis.domain.WxSendTemplateLog;
import com.fulihui.wgj.dal.mybatis.repository.WxSendTemplateLogRepository;
import com.fulihui.wgj.facade.dto.ClickNumStatisticDTO;
import com.fulihui.wgj.facade.dto.WxSendTemplateLogDTO;
import com.fulihui.wgj.facade.request.PrimaryKeyRequest;
import com.fulihui.wgj.facade.request.shortlink.ClickNumStatisticRequest;
import com.fulihui.wgj.facade.request.template.SendTemplateLogCancelRequest;
import com.fulihui.wgj.facade.request.template.SendTemplateLogPageQueryRequest;
import com.fulihui.wgj.facade.request.template.SendTemplateLogQueryRequest;
import com.fulihui.wgj.facade.request.template.TemplateLogSendUpdateRequest;
import com.fulihui.wgj.facade.result.template.SendTemplateLogPageResult;
import com.fulihui.wgj.facade.service.template.SendTemplateLogService;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 模板模板发送记录Service
 *
 * @author wang_wx
 * @date 2018-07-26
 */
@Component
@Service(interfaceClass = SendTemplateLogService.class, version = "1.0.0", timeout = 10000)
public class SendTemplateLogServiceImpl implements SendTemplateLogService {

    private static final Logger LOGGER = LoggerFactory.getLogger(SendTemplateLogServiceImpl.class);

    @Autowired
    private WxSendTemplateLogRepository wxSendTemplateLogRepository;

    @Autowired
    private TemplateMsgCancelUtil templateMsgCancelUtil;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    CommonProps commonProps;

    @Override
    public SendTemplateLogPageResult pageQuerySendLogs(SendTemplateLogPageQueryRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        Example example = buildExample4PageQuery(request);
        PageInfo<WxSendTemplateLog> pageInfo = wxSendTemplateLogRepository.queryPageListByExample(example, request.getPage(), request.getRows());
        long total = pageInfo.getTotal();
        SendTemplateLogPageResult pageResult = RpcResultBuilder.succPageResult(SendTemplateLogPageResult.class, pageInfo.getPageNum(), pageInfo.getPageSize(), Math.toIntExact(total));
        if (total > 0) {
            // 查询短链接点击数
            List<WxSendTemplateLogDTO> logDTOS = BeanConv.copy(pageInfo.getList(), WxSendTemplateLogDTO.class);
            if (!CollectionUtils.isEmpty(logDTOS)) {
                logDTOS.stream().forEach(logDTO -> {
                    try {
                        // 设置默认0
                        logDTO.setClickNum("--");
                        ClickNumStatisticRequest clickNumStatisticRequest = new ClickNumStatisticRequest();
                        ArrayList<String> urls = Lists.newArrayList();
                        Date startTime = logDTO.getSendStartTime();
                        Date endTime = new Date();
                        String jumpUrl = logDTO.getJumpUrl();
                        // 跳转链接不为空并且必须为短链的
                        String[] shortLinkHostList = commonProps.getShortLinkHostList();
                        if (StringUtils.isNotBlank(jumpUrl) && null != shortLinkHostList && shortLinkHostList.length > 0) {
                            List<String> strings = Arrays.asList(shortLinkHostList);
                            boolean containsUrl = false;
                            for (String string : strings) {
                                boolean contains = StringUtils.contains(jumpUrl, string);
                                if (contains) {
                                    containsUrl = true;
                                    break;
                                }
                            }
                            if (containsUrl) {
                                urls.add(jumpUrl);
                                clickNumStatisticRequest.setBeginTime(startTime);
                                clickNumStatisticRequest.setEndTime(endTime);
                                clickNumStatisticRequest.setUrls(urls);
                                String response = restTemplate.postForObject(commonProps.getShortLinkHost() + "/api/queryClickNumStatistic", clickNumStatisticRequest, String.class);
                                LOGGER.info("调用短链接进行查询点击数响应：response={}", response);
                                if (StringUtils.isNotBlank(response)) {
                                    JSONObject parseObject = JSONObject.parseObject(response);
                                    if ("00".equals(parseObject.get("code"))) {
                                        List<ClickNumStatisticDTO> dtoList = parseObject.getJSONArray("result").toJavaList(ClickNumStatisticDTO.class);
                                        if (!CollectionUtils.isEmpty(dtoList)) {
                                            ClickNumStatisticDTO statisticDTO = dtoList.get(0);
                                            Long clickNum = statisticDTO.getClickNum();
                                            logDTO.setClickNum(String.valueOf(clickNum));
                                        }
                                    }
                                }
                            }


                        }
                    } catch (Exception e) {
                        LOGGER.error("模板记录点击数调用短链系统发生错误", e);
                        return;
                    }
                });
            }
            pageResult.setValue(logDTOS);
        }
        return pageResult;
    }

    @Override
    public SimpleResult<List<WxSendTemplateLogDTO>> querySendLogs(SendTemplateLogQueryRequest request) throws InvokeServiceException {
        Example example = buildExample4Query(request);
        List<WxSendTemplateLog> wxSendTemplateLogs = wxSendTemplateLogRepository.queryByExample(example);
        List<WxSendTemplateLogDTO> templateLogDTOS = null;
        if (!CollectionUtils.isEmpty(wxSendTemplateLogs)) {
            templateLogDTOS = BeanConv.copy(wxSendTemplateLogs, WxSendTemplateLogDTO.class);
        }
        return RpcResultBuilder.succSimple(templateLogDTOS);
    }

    @Override
    public SimpleResult<List<WxSendTemplateLogDTO>> querySendLogs4Job() {
        Example example = new Example(WxSendTemplateLog.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("jobStatus", Boolean.TRUE);
        criteria.andEqualTo("sendStatus", SendLogStatusEnum.await.getCode());
        example.orderBy("jobTime").asc();
        List<WxSendTemplateLog> wxSendTemplateLogs = wxSendTemplateLogRepository.queryByExample(example);
        List<WxSendTemplateLogDTO> templateLogDTOS = null;
        if (!CollectionUtils.isEmpty(wxSendTemplateLogs)) {
            templateLogDTOS = BeanConv.copy(wxSendTemplateLogs, WxSendTemplateLogDTO.class);
        }
        return RpcResultBuilder.succSimple(templateLogDTOS);
    }

    /**
     * 组装分页的条件
     *
     * @param request
     * @return
     */
    private Example buildExample4Query(SendTemplateLogQueryRequest request) {
        Example example = new Example(WxSendTemplateLog.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("appId", request.getAppId());
        String sendStatus = request.getSendStatus();
        String beginDate = request.getBeginDate();
        String endDate = request.getEndDate();
        Integer templateLogType = request.getTemplateLogType();
        if (StringUtils.isNotBlank(sendStatus)) {
            criteria.andEqualTo("sendStatus", sendStatus);
        }
        if (StringUtils.isNotBlank(beginDate)) {
            criteria.andGreaterThanOrEqualTo("gmtModified", beginDate);
        }
        if (StringUtils.isNotBlank(endDate)) {
            criteria.andLessThanOrEqualTo("gmtModified", endDate);
        }
        if (Objects.nonNull(templateLogType)) {
            criteria.andEqualTo("templateLogType", templateLogType);
        }
        example.orderBy("gmtModified").desc();
        return example;
    }

    /**
     * 组装分页的条件
     *
     * @param request
     * @return
     */
    private Example buildExample4PageQuery(SendTemplateLogPageQueryRequest request) {
        Example example = new Example(WxSendTemplateLog.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("appId", request.getAppId());
        String sendStatus = request.getSendStatus();
        String beginDate = request.getBeginDate();
        String endDate = request.getEndDate();
        Integer templateLogType = request.getTemplateLogType();
        if (StringUtils.isNotBlank(sendStatus)) {
            criteria.andEqualTo("sendStatus", sendStatus);
        }
        if (StringUtils.isNotBlank(beginDate)) {
            criteria.andGreaterThanOrEqualTo("gmtModified", beginDate);
        }
        if (StringUtils.isNotBlank(endDate)) {
            criteria.andLessThanOrEqualTo("gmtModified", endDate);
        }
        if (Objects.nonNull(templateLogType)) {
            criteria.andEqualTo("templateLogType", templateLogType);
        }
        example.orderBy("gmtModified").desc();
        return example;
    }

    @Override
    public BaseResult cancelSendLog(SendTemplateLogCancelRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        WxSendTemplateLog exist = wxSendTemplateLogRepository.queryById(request.getId());
        if (Objects.isNull(exist)) {
            return RpcResultBuilder.fail(Errors.Commons.RECORD_NOT_EXISTS);
        }
        // 不是等待或者发送中的任务不允许取消
        if (SendLogStatusEnum.await.getCode().equals(exist.getSendStatus()) && SendLogStatusEnum.pushing.getCode().equals(exist.getSendStatus())) {
            return RpcResultBuilder.fail(Errors.WxTemplateLogError.CANNOT_CANCEL_NOT_PUSHING_OR_AWAIT_LOG);
        }
        WxSendTemplateLog templateLogUpdate = new WxSendTemplateLog();
        templateLogUpdate.setId(request.getId());
        templateLogUpdate.setSendStatus(SendLogStatusEnum.cancel.getCode());
        Integer count = wxSendTemplateLogRepository.updateSelective(templateLogUpdate);
        if (count > 0) {
            if (SendLogStatusEnum.pushing.getCode().equals(exist.getSendStatus())) {
                // 发送中的任务取消 将批次加入到redis中
                templateMsgCancelUtil.cancelTemplageMsg(String.valueOf(request.getId()));
            }
        }
        return count > 0 ? RpcResultBuilder.succ() : RpcResultBuilder.fail(Errors.Commons.UPDATE_FAILED);
    }

    @Override
    public BaseResult updateSendRecordAccumulate(TemplateLogSendUpdateRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        WxSendTemplateLog exist = wxSendTemplateLogRepository.queryById(request.getId());
        if (Objects.isNull(exist)) {
            return RpcResultBuilder.fail(Errors.Commons.RECORD_NOT_EXISTS);
        }
        WxSendTemplateLog templateLogUpdate = new WxSendTemplateLog();
        templateLogUpdate.setId(request.getId());
        templateLogUpdate.setGmtModified(new Date());
        templateLogUpdate.setSendStatus(request.getSendStatus());
        templateLogUpdate.setSuccessTotal(request.getSuccessTotal());
        templateLogUpdate.setFailTotal(request.getFailTotal());
        templateLogUpdate.setSendStartTime(request.getSendStartTime());
        templateLogUpdate.setSendEndTime(request.getSendEndTime());
        Integer count = wxSendTemplateLogRepository.updateAccumulate(templateLogUpdate);
        return count > 0 ? RpcResultBuilder.succ() : RpcResultBuilder.fail(Errors.Commons.UPDATE_FAILED);
    }

    @Override
    public SimpleResult<WxSendTemplateLogDTO> querySendLogById(PrimaryKeyRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        WxSendTemplateLog templateLog = wxSendTemplateLogRepository.queryById(request.getId());
        WxSendTemplateLogDTO templateLogDTO = null;
        if (Objects.nonNull(templateLog)) {
            templateLogDTO = BeanConv.copy(templateLog, WxSendTemplateLogDTO.class);
        }
        return RpcResultBuilder.succSimple(templateLogDTO);
    }
}
